import { useAppDispatch, useAppSelector } from '@/store/hooks'
import { RootState } from '@/types/store'
import { Action, ThunkAction } from '@reduxjs/toolkit'
import { useEffect } from 'react'

import { useMemoizedFn } from 'ahooks'

// 第三个参数默认值
// no oprate 表示一个空函数，不执行任何操作，一般常用做默认值
const noop = () => {}

// stateName 表示要获取 redux 状态中的某一个，所以，stateName 的类型应该是 Redux 中所有状态中的任意一个
// 而 keyof RootState 就是来获取 redux 中所有状态名称的联合类型
// StateName extends keyof RootState 表示： StateName 这个类型，应该是 redux 所有状态类型中的任意一个

// ThunkAction<void, RootState, unknown, Action> 4个类型变量：
//  第一个（void） 表示： thunk action 函数返回值的类型，此处指定为 void 表示对函数返回值的类型没有要求
//  第二个（RootState） 表示：redux 状态的类型
//  第三个（unknown） 表示：thunk action 的额外参数，我们没用使用，所以，直接设置为 unknown
//  第四个（Action） 表示：非 thunk action 的类型，此处，直接指定为 redux 中提供的 Action 类型
// 参考： https://redux.js.org/usage/usage-with-typescript#type-checking-redux-thunks
type ActionParam = () => ThunkAction<void, RootState, unknown, Action>
const useInitialState = <StateName extends keyof RootState>(
  action: ActionParam,
  stateName: StateName,
  // 注意：此处，是为参数设置默认值，不是添加类型
  afterAction = noop
) => {
  const dispatch = useAppDispatch()
  const state = useAppSelector(state => state[stateName])

  // 使用 useMemoizedFn hook 来记住 action
  const actionFn = useMemoizedFn(action)
  const afterActionFn = useMemoizedFn(afterAction)

  useEffect(() => {
    const loadData = async () => {
      await dispatch(actionFn())
      // 等到 action 执行完成后，在调用此处的函数
      afterActionFn()
    }
    loadData()
  }, [dispatch, actionFn, afterActionFn])

  // 将获取到的状态返回，这样，在调用这个 hook 的时候，才能拿到此处的状态
  return state
}

export { useInitialState }
